#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>
#include <linux/sockios.h>

#include <netinet/in.h>

#include <errno.h>

#define ETHERTYPE_ARP		0x0806
#define ETHERTYPE_IP		0x0800
#define MAC_BCAST_ADDR		"\xff\xff\xff\xff\xff\xff"

typedef struct arpMessage {
	struct ethhdr ethhdr;
	u_short htype;		/* hardware type (must be ARPHRD_ETHER) */
	u_short ptype;		/* protocol type (must be ETHERTYPE_IP) */
	u_char hlen;		/* hardware address length (must be 6) */
	u_char plen;		/* protocol address length (must be 4) */
	u_short operation;	/* ARP opcode */
	u_char sHaddr[ETH_ALEN];	/* sender's hardware address */
	u_char sInaddr[4];	/* sender's IP address */
	u_char tHaddr[ETH_ALEN];	/* target's hardware address */
	u_char tInaddr[4];	/* target's IP address */
	u_char pad[18];		/* pad for min. Ethernet payload (60 bytes) */
} arpMessage;

#define auto_ip_debug(fmt,...) printf((fmt), ##__VA_ARGS__)

/**
 *Description: builds different kinds of arp messages
 *@param msg: the msg to be built
 *@param opcode: indicates the kind of operation
 *@param tipaddr: target ip address
 *@param thaddr: target hardware address
 *@param sipaddr: source ip address
 *@param shaddr: source hardware address
 */
void set_arp_msg(arpMessage * msg, const u_short opcode, const u_long tipaddr, const u_char * thaddr,
		 const u_long sipaddr, const u_char * shaddr);

/**
 *Description: checks whether an ip address is in use or not
 *@param taddr: target ip address to be checked
 *return 1 if this ip address is in use, otherwise return 0
 */
int check_ip_used(const u_long ip_to_check, const u_char * my_hw_addr);

/**
 *Description: sends Gratuitous Arp messages to inform others of this ip address
 *@param addr: the ip address to be informed
 *return -1 when an error occurs, otherwise return 0
 */
int send_gra_arp(const u_long addr, const u_char * my_hw_addr);
